package receptor;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import pool.RejectHandler;
import pool.Task;

public class ProcessorServer extends Thread {
	
	private static final int PORT_LOW = 5180;
	
	protected DatagramSocket socket = null;
	protected BufferedReader in = null;
	protected boolean active = true;
	
	private SimpleDateFormat fmt;
	
	private final boolean wantExceptionOnReject = false;
	
	private final int poolCoreSize = 600;
	private final int poolMaxSize = 600;
	private final int keepAliveTime = 4000;
	
	private BlockingQueue<Runnable> queue;
	private ThreadPoolExecutor executor;
	
	public ProcessorServer(String name) throws SocketException{
		super(name);
		socket = new DatagramSocket(PORT_LOW);
		fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
		
		queue = new ArrayBlockingQueue<Runnable>(100, true);
		executor = new ThreadPoolExecutor(poolCoreSize, poolMaxSize, keepAliveTime, TimeUnit.MILLISECONDS, queue);
	}
	
	public void run(){
		
		if(!wantExceptionOnReject){
			executor.setRejectedExecutionHandler(new RejectHandler());
		}
		
		while(active){
			
			try {
				byte[] bufIn = new byte[256];
				byte[] bufOut = new byte[256];
				
				//Recibe el paquete
				DatagramPacket packet = new DatagramPacket(bufIn, bufIn.length);
				socket.receive(packet);
				
				Task t = new Task("Frame--" + fmt.format(new Date()), bufIn);
				
				try{
					executor.execute(t);
				}
				catch(RejectedExecutionException e){
					e.printStackTrace();
				}
				
				String response = "Paquete recibido -- " + new Date().toString();
				
				bufOut = response.getBytes();
				
				//Enviar la respuesta
				InetAddress address = packet.getAddress();
				int port = packet.getPort();
				packet = new DatagramPacket(bufOut, bufOut.length, address, port);
				socket.send(packet);
			} 
			catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
		
		socket.close();
	}

}
